//---------------------------------------------------------------------------
#ifndef CTarBz2H
#define CTarBz2H
//---------------------------------------------------------------------------
#include "bzlib.h"
#include "libtar.hpp"
//---------------------------------------------------------------------------
// Numéros d'erreur pouvant être attribué à BZ2Exception
// Attention, il existe d'autres numéros d'erreur ds 'bzlib.h'
#define ERROR_LOAD_BZ2_LIB    ( -1000)
#define ERROR_OPEN_BZ2_FILE   ( -1001)
#define ERROR_VERY_OLD_BZ2    ( -1002)
//---------------------------------------------------------------------------
enum TARBZ2_STATUS { TBZ2_NONE, TBZ2_INIT, TBZ2_IMPLODE, TBZ2_EXPLODE };
//---------------------------------------------------------------------------
// Exception pouvant être déclencher par l'objet du flux BZ2
class PACKAGE BZ2Exception : public Exception
{
  private:
    int m_nError;
  public:
    __fastcall BZ2Exception( int nError);
    __property int Error = { read=m_nError };
};
//---------------------------------------------------------------------------
// Nouveaux prototypes d'évènement
typedef void __fastcall ( __closure *TAcceptDirEvent )( TObject *pSender, const AnsiString &strStartDirectory, const AnsiString &strDirectory, bool &bAccept);
typedef void __fastcall ( __closure *TAcceptFileEvent)( TObject *pSender, const AnsiString &strStartDirectory, const AnsiString &strDirectory, const AnsiString &strFilename, bool &bAccept);
typedef void __fastcall ( __closure *TGaugeEvent     )( TObject *pSender, int nPourcent);
typedef void __fastcall ( __closure *TAcceptExplode  )( TObject *pSender, bool &bAccept);
typedef void __fastcall ( __closure *TArchiveExists  )( TObject *pSender, const AnsiString &strArchiveName, bool &bCanErase);
//---------------------------------------------------------------------------
#define CACHE_SIZE ( 512*1024)
class TBZ2Stream;
class PACKAGE CTarBZ2 : public TComponent
{
  private:
    AnsiString        m_strStartDir; // Répertoire à compresser ou répertoire d'extraction dans le cas de la décompression
    TBZ2Stream       *m_bz2Stream;   // Flux de compression/décompression au format BZ2
    TTarWriter       *m_tarWriter;   // Objet pour permettre l'archivage dans une fichier TAR
    TFileStream      *m_fileStream;  // Flux d'accès au fichier final

    TAcceptDirEvent   m_evAcceptDirectory; // Evènements
    TAcceptFileEvent  m_evAcceptFile;      //     "
    TAcceptExplode    m_evAcceptExplode;   //     "
    TGaugeEvent       m_evProgress;        //     "
    TNotifyEvent      m_evStart;           //     "
    TNotifyEvent      m_evTerminate;       //     "
    TArchiveExists    m_evArchiveExists;   //     "

    int               m_nMaxProgress; // Progression max
    int               m_nProgress;    // Progression en cours
    int               m_nPourcent;    // Progression en cours en %

    int               m_nBlockSize;   // Taille du bloc (correspond au niveau de compression voulu) valeur de 1(fast) à 9(best)
    bool              m_bSmall;       // Flag déterminant si l'on doit utiliser un minimum de mémoire pour la décompression

    TARBZ2_STATUS     m_eStatus;
    TStrings         *m_lstrUserDatas; // Liste des paramètres à mettre dans le fichier spécial

    bool              m_bRemovableDevice;  // Permet de savoir si on travail sur un support amovible
    bool              m_bImplode;          // Permet de savoir si on sauvegarde ou si on restaure
    int               m_nSupport;          // Numéro du support en cours
    int               m_nReadFile;         // Nombre d'octets lus dans l'archive
    unsigned __int64  m_u64FreeSpace;      // Espace libre sur le support en cours
    AnsiString        m_strFilename;       // Nom de l'archive

    int               m_nCache;            // Taille du cache utilisé
    char             *m_szCache;           // Cache pour accélérer la sauvegarde sur disquette

    // Fonction à usage interne (voir CTarBz2.cpp)
    void __fastcall AddFiles( const AnsiString &strDir);
    int  __fastcall CalculateMaxFiles( const AnsiString &strDir);
    void __fastcall InitImplodeExplode( TARBZ2_STATUS eOperation);

    void __fastcall SetBlockSize( int nValue);
    void __fastcall SetUserDatas( TStrings *lstrValue);

    bool __fastcall InsertNewFloppy( const AnsiString &strFilename);
    bool __fastcall InsertNewSupportAndOpen( void);
    int  __fastcall WriteDatas( LPVOID lpvBuffer, int nCount);
    int  __fastcall ReadDatas( LPVOID lpvBuffer, int nCount);
    void __fastcall FlushDatas( Word wMode);

    // Appel des évènements
    void __fastcall Start( void);
    void __fastcall Terminate( void);
    bool __fastcall AcceptDirectory( const AnsiString &strNewDir);
    bool __fastcall AcceptFile( const AnsiString &strDir, const AnsiString &strFilename);
    bool __fastcall AcceptExplode( void);

  public:
            __fastcall  CTarBZ2( TComponent *pOwner);
    virtual __fastcall ~CTarBZ2( void);

    // Fonctions de compression/décompression
    void __fastcall Implode( const AnsiString &strFilenameTBZ2, const AnsiString &strPath);
    void __fastcall Explode( const AnsiString &strFilenameTBZ2, const AnsiString &strPath);

    // Retourne le status du composant INIT, IMPLODE, EXPLODE, NONE
    __property TARBZ2_STATUS Status = { read=m_eStatus };

  __published:
    // Vitesse et performance de compression 1(fast)-9(best)
    __property int  BlockSize   = { read=m_nBlockSize, write=SetBlockSize, default=9     };
    // Permet d'utiliser moins de mémoire pendant la décompression
    __property bool Small       = { read=m_bSmall    , write=m_bSmall    , default=false };

    // Valeur à mettre dans le fichier spécial
    // Utilisation recommandée
    //   CTarBz2->UserDatas->Values["NomDossier" ] = "DOSSIER DEMONSTRATION";
    //   CTarBz2->UserDatas->Values["ExericeNdeb"] = "01/01/2002";
    //   CTarBz2->UserDatas->Values["ExericeNfin"] = "31/12/2002";
    __property TStrings *UserDatas = { read=m_lstrUserDatas, write=SetUserDatas };

    // Durant la compression
    //   Attention les fonctions OnAcceptDirectory et OnAcceptFile sont appelées
    //   2 fois de façon identique si l'on a demandé un évènement de progression
    //   1er fois pour connaitre le nombre de fichiers à archiver
    //   2ème fois lors de l'archivage
    // Durant la décompression
    //   Seul l'évènement OnAcceptFile est appelé
    __property TAcceptDirEvent  OnAcceptDirectory = { read=m_evAcceptDirectory, write=m_evAcceptDirectory };
    __property TAcceptFileEvent OnAcceptFile      = { read=m_evAcceptFile     , write=m_evAcceptFile      };

    // Evènement déclenché seulement s'il existe des données utilisateurs.
    // Permet d'abandonner la décompression, par exemple dans le cas d'un fichier
    // que l'on a protégé artificiellement par un mot de passe.
    __property TAcceptExplode   OnAcceptExplode   = { read=m_evAcceptExplode  , write=m_evAcceptExplode   };

    __property TArchiveExists   OnArchiveExists   = { read=m_evArchiveExists  , write=m_evArchiveExists   };

    // Evènement pour gérer la progression des traitements (compression/décompression)
    // La variable 'nPourcent' correspond au pourcentage du traitement effectué
    __property TGaugeEvent      OnProgress        = { read=m_evProgress       , write=m_evProgress        };

    // Sans commentaire
    __property TNotifyEvent     OnStart           = { read=m_evStart          , write=m_evStart           };
    __property TNotifyEvent     OnTerminate       = { read=m_evTerminate      , write=m_evTerminate       };
};
//---------------------------------------------------------------------------
#endif
